﻿using System;
using System.IO;
using System.Text;

namespace WikiDoc.Reader
{
    /// <summary>
    /// 
    /// </summary>
    public abstract class TextReaderPipe : TextReader, IResetable
    {
        /// <summary>
        /// Initializes a new instance of the TrimReader class.
        /// </summary>
        /// <param name="reader">The reader.</param>
        public TextReaderPipe(TextReader reader)
        {
            if (reader == null)
            {
                throw new ArgumentNullException("reader");
            }

            _BaseReader = reader;
        }

        private TextReader _BaseReader;
        /// <summary>
        /// Gets the base stream.
        /// </summary>
        /// <value>The base stream.</value>
        public TextReader BaseReader
        {
            get
            {
                return _BaseReader;
            }
            set
            {
                if (value == null)
                {
                    throw new ArgumentNullException("value");
                }

                _BaseReader = value;
            }
        }

        /// <summary>
        /// 从当前流中读取一行字符并将数据作为字符串返回。
        /// </summary>
        /// <returns>输入流的下一行，或者如果已读取了所有字符，则为 null。</returns>
        /// <exception cref="T:System.IO.IOException">发生 I/O 错误。 </exception>
        /// <exception cref="T:System.OutOfMemoryException">内存不足，无法为返回的字符串分配缓冲区。 </exception>
        /// <exception cref="T:System.ObjectDisposedException"><see cref="T:System.IO.TextReader"></see> 是关闭的。 </exception>
        /// <exception cref="T:System.ArgumentOutOfRangeException">下一行中的字符数大于 <see cref="F:System.Int32.MaxValue"></see></exception>
        public override string ReadLine()
        {
            return BaseReader.ReadLine();
        }

        /// <summary>
        /// 关闭 <see cref="TextReader"></see> 并释放与该 TextReader 关联的所有系统资源。
        /// </summary>
        public override void Close()
        {
            try
            {
                _BaseReader.Close();
            }
            finally
            {
                base.Close();
            }
        }

        /// <summary>
        /// 读取下一个字符，而不更改读取器状态或字符源。返回下一个可用字符，而实际上并不从输入流中读取此字符。
        /// </summary>
        /// <returns>下一个要读取的字符，或者如果没有更多的可用字符或此流不支持查找，则为 -1。</returns>
        /// <exception cref="T:System.ObjectDisposedException"><see cref="T:System.IO.TextReader"></see> 是关闭的。 </exception>
        /// <exception cref="T:System.IO.IOException">发生 I/O 错误。 </exception>
        public override int Peek()
        {
            return _BaseReader.Peek();
        }

        /// <summary>
        /// 读取输入流中的下一个字符并使该字符的位置提升一个字符。
        /// </summary>
        /// <returns>
        /// 输入流中的下一个字符，或者如果没有更多的可用字符，则为 -1。默认实现将返回 -1。
        /// </returns>
        /// <exception cref="T:System.ObjectDisposedException"><see cref="T:System.IO.TextReader"></see> 是关闭的。 </exception>
        /// <exception cref="T:System.IO.IOException">发生 I/O 错误。 </exception>
        public override int Read()
        {
            return _BaseReader.Read();
        }

        /// <summary>
        /// 从当前流中读取最大 count 的字符并从 index 开始将该数据写入 buffer。
        /// </summary>
        /// <param name="buffer">此方法返回时，包含指定的字符数组，该数组的 index 和 (index + count - 1) 之间的值由从当前源中读取的字符替换。</param>
        /// <param name="index">buffer 中开始写入的位置。</param>
        /// <param name="count">最多读取的字符数。如果在将 count 个字符读入 buffer 之前已到达流的末尾，则当前方法将返回。</param>
        /// <returns>
        /// 已读取的字符数。该数小于或等于 count，具体取决于流中是否有可用的数据。如果调用此方法时没有更多的字符留下可供读取，则此方法返回 0。
        /// </returns>
        /// <exception cref="T:System.ArgumentOutOfRangeException">index 或 count 为负。 </exception>
        /// <exception cref="T:System.ObjectDisposedException"><see cref="T:System.IO.TextReader"></see> 是关闭的。 </exception>
        /// <exception cref="T:System.ArgumentException">缓冲区长度减去 index 小于 count。 </exception>
        /// <exception cref="T:System.IO.IOException">发生 I/O 错误。 </exception>
        /// <exception cref="T:System.ArgumentNullException">buffer 为 null。 </exception>
        public override int Read(char[] buffer, int index, int count)
        {
            return _BaseReader.Read(buffer, index, count);
        }

        /// <summary>
        /// 从当前流中读取最大 count 的字符并从 index 开始将该数据写入 buffer。
        /// </summary>
        /// <param name="buffer">此方法返回时，此参数包含指定的字符数组，该数组中从 index 到 (index + count -1) 之间的值由从当前源中读取的字符替换。</param>
        /// <param name="index">buffer 中开始写入的位置。</param>
        /// <param name="count">最多读取的字符数。</param>
        /// <returns>
        /// 已读取的字符数。该数字将小于或等于 count，具体取决于是否所有的输入字符都已读取。
        /// </returns>
        /// <exception cref="T:System.ArgumentOutOfRangeException">index 或 count 为负。 </exception>
        /// <exception cref="T:System.ObjectDisposedException"><see cref="T:System.IO.TextReader"></see> 是关闭的。 </exception>
        /// <exception cref="T:System.ArgumentException">缓冲区长度减去 index 小于 count。 </exception>
        /// <exception cref="T:System.IO.IOException">发生 I/O 错误。 </exception>
        /// <exception cref="T:System.ArgumentNullException">buffer 为 null。 </exception>
        public override int ReadBlock(char[] buffer, int index, int count)
        {
            return _BaseReader.ReadBlock(buffer, index, count);
        }

        /// <summary>
        /// 读取从当前位置到 TextReader 的结尾的所有字符并将它们作为一个字符串返回。
        /// </summary>
        /// <returns>包含从当前位置到 TextReader 的结尾的所有字符的字符串。</returns>
        /// <exception cref="T:System.IO.IOException">发生 I/O 错误。 </exception>
        /// <exception cref="T:System.OutOfMemoryException">内存不足，无法为返回的字符串分配缓冲区。 </exception>
        /// <exception cref="T:System.ObjectDisposedException"><see cref="T:System.IO.TextReader"></see> 是关闭的。 </exception>
        /// <exception cref="T:System.ArgumentOutOfRangeException">下一行中的字符数大于 <see cref="F:System.Int32.MaxValue"></see></exception>
        public override string ReadToEnd()
        {
            StringBuilder sb = new StringBuilder();
            string line;

            while ((line = ReadLine()) != null)
            {
                sb.AppendLine(line);
            }

            return sb.ToString();
        }

        /// <summary>
        /// 释放由 <see cref="T:System.IO.TextReader"></see> 占用的非托管资源，还可以另外再释放托管资源。
        /// </summary>
        /// <param name="disposing">为 true 则释放托管资源和非托管资源；为 false 则仅释放非托管资源。</param>
        protected override void Dispose(bool disposing)
        {
            try
            {
                _BaseReader.Dispose();
            }
            finally
            {
                base.Dispose(disposing);
            }
        }

        /// <summary>
        /// Appends the specified reader.
        /// </summary>
        /// <param name="reader">The reader.</param>
        public void Append(TextReaderPipe reader)
        {
            if (reader == null)
            {
                throw new ArgumentNullException("reader");
            }

            reader.BaseReader = _BaseReader;
            _BaseReader = reader;
        }

        /// <summary>
        /// Resets this instance.
        /// </summary>
        public virtual void Reset()
        {
            if (_BaseReader is IResetable)
            {
                IResetable obj = (IResetable)_BaseReader;
                obj.Reset();
            }
        }

    }
}